/*************************************************************************
	> File Name: visitor.h
	> Author: ma6174
	> Mail: ma6174@163.com 
	> Created Time: 2021年12月13日 星期一 21时06分53秒
 ************************************************************************/

#include<iostream>
#include <string>
#include <list>
#include <typeinfo>

//抽象类

struct Element;

struct Visitor
{
	virtual void visitConcreteElementA(Element* elemA) = 0;
	virtual void visitConcreteElementB(Element* elemB) = 0;
};

struct Element
{
	virtual void accept(Visitor* visitor) = 0;
};

//Visitor具体类
struct ConcreteVisitor1 : public Visitor
{
	virtual void visitConcreteElementA(Element* elemA)
	{
		std::cout << std::string(typeid(*elemA).name()) << " 被 " << std::string(typeid(*this).name()) << " 访问!" << std::endl; 
	}

	virtual void visitConcreteElementB(Element* elemB)
	{
		std::cout << std::string(typeid(*elemB).name()) << " 被 " << std::string(typeid(*this).name()) << " 访问!" << std::endl;
	}
};

struct ConcreteVisitor2 : public Visitor
{
	virtual void visitConcreteElementA(Element* elemA)
	{
		std::cout << std::string(typeid(*elemA).name()) << " 被 " << std::string(typeid(*this).name()) << " 访问!" << std::endl; 
	}

	virtual void visitConcreteElementB(Element* elemB)
	{
		std::cout << std::string(typeid(*elemB).name()) << " 被 " << std::string(typeid(*this).name()) << " 访问!" << std::endl;
	}
};


//具体Element类
struct ConcreteElementA : public Element
{
	virtual void accept(Visitor* visitor)
	{
		visitor->visitConcreteElementA(this);
	}
};

struct ConcreteElementB : public Element
{
	virtual void accept(Visitor* visitor)
	{
		visitor->visitConcreteElementB(this);
	}
};

class ObjectStructure
{
public:
	~ObjectStructure()
	{
		for (auto elem : elements)
			delete elem;
	}

	void attach(Element* elem)
	{
		elements.push_back(elem);
	}

	void detach(Element* elem)
	{
		elements.remove(elem);
	}

	void accept(Visitor* visitor)
	{
		for (auto elem : elements)
			elem->accept(visitor);
	}

private:
	std::list<Element*> elements;
};
